﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Configuration;

using ExtensibleEventViewer.Core.Interfaces;


namespace ExtensibleEventViewer.Console.DomainModel
{
	public class AppSettings : ApplicationSettingsBase
	{
		private const string EVENT_LOGS_TO_MONITOR = "EventLogsToMonitor";
		private const string COMPUTER_LIST = "ComputerList";
		private const string REFRESH_TIME_INTERVAL = "RefreshTimeInterval";
		private const string ENABLE_AUTO_REFRESH = "EnableAutoRefresh";
		private const string ADAPTER_SETTINGS = "AdapterSettings";
		private const string ENABLED_EVENT_LOG_FILTERS = "EnabledEventLogFilters";


		private readonly static AppSettings _instance = new AppSettings();

		protected AppSettings()
		{
			PropertyChanged += AppSettings_PropertyChanged;

			Initialize();
		}

		private void Initialize()
		{
			ComposablePartCatalog catalog = new DirectoryCatalog(".");

			using (CompositionContainer container = new CompositionContainer(catalog))
			{
				CompositionBatch batch = new CompositionBatch();
				batch.AddPart(this);

				container.Compose(batch);
			}
		}

		[Import(typeof(IEventLogProvider))]
		public IEnumerable<IEventLogProvider> EventLogProviders;

		[Import(typeof(IEventLogFilter))]
		public IEnumerable<IEventLogFilter> EventLogFilters;

		public Action<PropertyChangedEventArgs> SavingFailed;


		public static AppSettings Instance
		{
			get
			{
				return _instance;
			}
		}
		

		[UserScopedSetting]
		public TrackedEventLog[] EventLogsToMonitor
		{
			get
			{
				return this[EVENT_LOGS_TO_MONITOR] == null 
				       	?
							new TrackedEventLog[0] 
				       	:
							this[EVENT_LOGS_TO_MONITOR] as TrackedEventLog[];
			}
			set
			{
				this[EVENT_LOGS_TO_MONITOR] = value;
			}
		}

		[UserScopedSetting]
		public string[]  ComputerList
		{
			get
			{
				return this[COMPUTER_LIST] == null
						?
							new string[0]
						:
							this[COMPUTER_LIST] as string[];
			}
			set
			{
				this[COMPUTER_LIST] = value;
			}
		}

		[UserScopedSetting]
		public TimeSpan RefreshTimeInterval
		{
			get
			{
				return this[REFRESH_TIME_INTERVAL] == null
						?
							new TimeSpan()
						:
							(TimeSpan)this[REFRESH_TIME_INTERVAL];

			}
			set
			{
				this[REFRESH_TIME_INTERVAL] = value;
			}
		}

		[UserScopedSetting]
		public bool EnableAutoRefresh
		{
			get
			{
				return this[ENABLE_AUTO_REFRESH] == null
						?
							false
						:
							(bool)this[ENABLE_AUTO_REFRESH];

			}
			set
			{
				this[ENABLE_AUTO_REFRESH] = value;
			}
		}

		[UserScopedSetting]
		public EventLogAdapterSettingsData[] AdapterSettings
		{
			get
			{
				return this[ADAPTER_SETTINGS] == null
				       	?
				       		new EventLogAdapterSettingsData[0]
				       	:
				       		(EventLogAdapterSettingsData[]) this[ADAPTER_SETTINGS];
			}
			set
			{
				this[ADAPTER_SETTINGS] = value;
			}
		}

		[UserScopedSetting]
		public KeyValuePair<string, bool>[] EnabledEventLogFilters
		{
			get
			{
				if (this[ENABLED_EVENT_LOG_FILTERS] == null)
				{
					List<KeyValuePair<string,bool>> enabledFilters =new List<KeyValuePair<string, bool>>();

					foreach (IEventLogFilter filter in EventLogFilters)
					{
						enabledFilters.Add(new KeyValuePair<string, bool>(filter.FilterID, true));
					}

					this[ENABLED_EVENT_LOG_FILTERS] = enabledFilters.ToArray();
				}


				return (KeyValuePair<string, bool>[])this[ENABLED_EVENT_LOG_FILTERS];
			}
			set
			{
				this[ENABLED_EVENT_LOG_FILTERS] = value;
			}
		}


		private void AppSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			try
			{
				Save();
			}
			catch
			{
				if (SavingFailed != null)
				{
					SavingFailed(e);
				}
			}
		}
	}
}